home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dviapollo
/
xinteract.c
< prev
Wrap
C/C++ Source or Header
|
1990-10-01
|
14KB
|
529 lines
/* @(#)xinteract.c 1.6 2/18/87 */
#include "header.h"
#include <X/Xlib.h>
#include "gray1.bitmap"
#define DEFAULTFONT "vtsingle"
#define BUTTONMARGIN 4
Window frame;
Window panel;
Window textwindow;
int screenheight = 0;
int screenwidth = 0;
int textwindowheight = 0;
/* State information for the filename item. */
Window filename_button;
char *current_file_name;
int current_file_name_index;
int current_file_name_length;
/* State information for the region that displays the error messages. */
Window error_button;
char *error_message;
/* State information for the page number slider. */
/* This window has all of the graphics for the slider. */
Window page_window;
/* This window just has the slider bar itself. It's a subwindow of */
/* page_window. */
Window page_subwindow;
Pixmap page_tile;
int page_max = 1;
int page_current = 1;
int page_displayed;
/* X coordinate of page_subwindow in page_window. */
int pager_x = 0;
#define PAGER_WIDTH 100
/* Whether or not to carry on in reverse video. */
BOOLEAN reversevideo;
Pixmap foreground, background;
XAssocTable *callouttable; /* Assoc table for storing mapping from */
/* buttons to callout routines. */
XAssocTable *offsets; /* Assoc table to remember how much the labels */
/* need to be shifted right to be centered. */
Font font;
FontInfo fontinfo;
BOOLEAN reverse_video_p ();
char *realloc ();
/* On window w, coordinates (x,y) draw the text in chars. */
void dotext (w, x, y, chars)
Window w;
int x, y;
char *chars;
{
XTextPad (w, x, y, chars, strlen (chars), font, 0, 0,
WhitePixel, BlackPixel, reversevideo?GXor:GXandInverted,
AllPlanes);
}
void black_box (x, y, width, height)
int x, y, width, height;
{
XPixFill (textwindow, x, y, width, height,
reversevideo?WhitePixel:BlackPixel, 0,
GXcopy, AllPlanes);
}
int screen_height ()
{
return (textwindowheight);
}
/* Cribbed from /usr/misc/X/libsun/initial.c. */
static unsigned char InvPix[256];
SetUpInvPix()
{
register int i;
for (i = 255; i >= 0; i--) {
register int j = 1, k = 128, l = 8;
while (l--) {
if ((i & j) != 0)
InvPix[i] |= k;
j <<= 1;
k >>= 1;
}
}
}
/* Cribbed from /usr/misc/X/libsun/util.c. */
InvertPixelOrder(p, n)
register unsigned short *p;
register int n;
{
for (; n--; p++) {
register unsigned short l = (*p & 0xff), h = (*p >> 8)&0xff;
unsigned short old = *p;
*p = (unsigned short) ((InvPix[l] << 8) | InvPix[h]);
}
}
/* Read a character from a font file, with the given width and height. */
/* For X, a CharImage is a Pixmap. */
CharImage read_char (pxlfp, width, height)
FILE *pxlfp;
int width, height;
{
static short *bitmapbuf = NULL;
static int bitmapbufsize = 0;
register int nshorts, i, col, nints;
register short *dp, *sp;
static int buffer[8];
Bitmap result;
if (!bitmapbuf) {
bitmapbuf = (short *) malloc (1);
bitmapbufsize = 1;
};
if (bitmapbufsize < BitmapSize (width, height)) {
bitmapbufsize = BitmapSize (width, height);
bitmapbuf = (short *)realloc (bitmapbuf, bitmapbufsize);
};
if (!bitmapbuf) {
fprintf (stderr, "Memory allocation failed in read_char.\n");
exit (1);
}
nshorts = (width + 15) >> 4;
nints = (nshorts + 1) >> 1;
dp = bitmapbuf;
for (col = 0; col < height; col++) {
fread(buffer, 4, nints, pxlfp);
sp = (short *) &buffer[0];
for (i = nshorts; i > 0; i--) *dp++ = *sp++;
}
InvertPixelOrder (bitmapbuf, BitmapSize (width, height) >> 1);
result = XStorePixmapXY (width, height, bitmapbuf);
if (!result) {
fprintf (stderr, "Pixmap creation failed in read_char.\n");
exit (1);
}
return ((CharImage) result);
}
void show_char (x, y, width, height, image)
int x, y, width, height;
CharImage image;
{
if (((x + width) >= 0) &&
(x < screenwidth) &&
((y + height) >= 0) &&
(y < screenheight)) {
XPixmapPut (textwindow, 0, 0, x, y, width, height, (Pixmap) image,
reversevideo?GXor:GXandInverted, AllPlanes);
}
};
void clearscreen ()
{
XClear (textwindow);
}
void lock_canvas ()
{
}
void unlock_canvas ()
{
}
char *curfilename ()
{
return (current_file_name);
}
/* Refresh the image of the slider. */
void refresh_slider ()
{
char buffer [20];
XClear (page_window);
XClear (page_subwindow);
if (page_max > 1) {
sprintf (buffer, "Pages: [%d]", page_displayed);
dotext (page_window, BUTTONMARGIN, BUTTONMARGIN, buffer);
XTileSet (page_subwindow, 0, 0,
(int) ((float) (page_displayed - 1) / (page_max - 1) * PAGER_WIDTH),
fontinfo.height, page_tile);
}
}
/* Set the slider so that it has pages pages displayed. */
void show_slider (pages)
int pages;
{
char buffer [20];
page_max = pages;
page_current = 1;
page_displayed = 1;
if (page_max == 1) {
XUnmapWindow (page_subwindow);
} else {
XMapWindow (page_subwindow);
sprintf (buffer, "%d", page_max);
XConfigureWindow (page_subwindow,
BUTTONMARGIN +
(strlen ("Page: [] ") + strlen (buffer) + 1) *
fontinfo.width,
BUTTONMARGIN,
PAGER_WIDTH,
fontinfo.height);
}
refresh_slider ();
}
/* Update the current (not the maximum) number of pages displayed on */
/* the slider.*/
void update_slider (pages)
int pages;
{
page_current = pages;
page_displayed = pages;
refresh_slider ();
}
void curpage_from_x (event)
XEvent *event;
{
int new_displayed;
if (page_max > 1) {
new_displayed = (int) ((float) ((XKeyEvent *) event) -> x /
PAGER_WIDTH * (page_max - 1) + 0.5) + 1;
if (new_displayed != page_displayed) {
page_displayed = new_displayed;
refresh_slider ();
};
}
}
int lines_to_y (lines)
int lines;
{
return (lines * (fontinfo.height + 3 * BUTTONMARGIN) +
BUTTONMARGIN);
}
int chars_to_x (chars)
int chars;
{
return (chars * fontinfo.width - BUTTONMARGIN);
}
/* This puts a button image on the screen. It is called by
create_buttons.
name is the label for the button. It needs to be centered.
width is the width in characters of the button.
x,y, are the position of the button on a character grid.
callout is the procedure to call when the button is pushed.
*/
void create_a_button (name, width, x, y, callout)
char *name;
int width, x, y;
void (*callout) ();
{
Window created;
created = XCreateWindow (panel, chars_to_x (x), lines_to_y (y),
width * fontinfo.width + 2 * BUTTONMARGIN,
fontinfo.height + 2 * BUTTONMARGIN, 1,
foreground, background);
XStoreName (created, name);
XMakeAssoc (callouttable, created, callout);
XMakeAssoc (offsets, created,
((width - strlen (name)) >> 1) * fontinfo.width);
XSelectInput (created, ButtonReleased | ExposeWindow);
}
void update_filename ()
{
char *namestart;
if (strlen (current_file_name) > 19) {
namestart = current_file_name + (strlen (current_file_name) - 19);
} else {
namestart = current_file_name;
}
XClear (filename_button);
{
char buffer [35];
sprintf (buffer, "Filename: %s", namestart);
dotext (filename_button, BUTTONMARGIN, BUTTONMARGIN, buffer);
}
}
void update_error ()
{
XClear (error_button);
dotext (error_button, BUTTONMARGIN, BUTTONMARGIN, error_message);
}
void showerror (string)
char *string;
{
error_message = string;
update_error ();
}
void clearerror ()
{
error_message = "";
update_error ();
}
void main (argc, argv)
int argc;
char **argv;
{
int downx = 0, downy = 0;
int panelheight;
SetUpInvPix ();
if ((PXLpath = getenv ("BGPXLPATH")) == NULL)
PXLpath = FONTAREA;
error_message = "";
current_file_name = malloc (10);
current_file_name_index = 0;
current_file_name_length = 10;
{
char *thisch = argv [1];
if (thisch) {
for (;*thisch;thisch++) {
vector_push_extend (¤t_file_name_index,
¤t_file_name_length,
¤t_file_name,
sizeof (char));
current_file_name [current_file_name_index - 1] = *thisch;
}
}
}
vector_push_extend (¤t_file_name_index,
¤t_file_name_length,
¤t_file_name,
sizeof (char));
current_file_name [current_file_name_index - 1] = '\0';
if (!XOpenDisplay ("unix:0")) {
fprintf (stderr, "Could not open the display.\n");
exit (1);
};
reversevideo = reverse_video_p (argv [0]);
foreground = reversevideo?WhitePixmap:BlackPixmap;
background = reversevideo?BlackPixmap:WhitePixmap;
page_tile = XStorePixmapXY (gray1_width, gray1_height, gray1_bits);
{
char *fontname = XGetDefault (argv [0], "Font");
if (fontname == NULL) fontname = DEFAULTFONT;
if (!(font = XGetFont (fontname))) {
fprintf (stderr, "Couldn't open font %s for buttons.\n", fontname);
exit (1);
};
XQueryFont (font, &fontinfo);
}
/* This is the inside height. */
panelheight = lines_to_y (2);
{
OpaqueFrame oframe;
WindowInfo info;
char defgeom [20];
oframe.border = foreground;
oframe.background = background;
oframe.bdrwidth = 1;
sprintf (defgeom, "=%dx%d+0+0",
DisplayWidth()-2,
DisplayHeight()-2);
frame = XCreate (argv [0], argv [0],
0, defgeom,
&oframe,
chars_to_x (70) + BUTTONMARGIN +PAGER_WIDTH,
2 * panelheight);
XSelectInput (frame, ExposeWindow | ButtonPressed
| ButtonReleased
| KeyPressed);
XQueryWindow (frame, &info);
screenwidth = info.width;
screenheight = info.height;
panel = XCreateWindow (frame, -1, -1, screenwidth,
panelheight, 1, foreground, background);
textwindowheight = screenheight - panelheight;
/* The border pixmap below is background so we can have an */
/* invisible border. We want a border, though, so that this */
/* window lines up with the buttons. */
filename_button = XCreateWindow (panel,
chars_to_x (0), lines_to_y (0),
chars_to_x (30), lines_to_y (1),
1, background, background);
XSelectInput (filename_button, ExposeWindow);
error_button = XCreateWindow (panel,
chars_to_x (0), lines_to_y (1),
chars_to_x (30), lines_to_y (1),
1, background, background);
XSelectInput (error_button, ExposeWindow);
page_window = XCreateWindow (panel,
chars_to_x (57), lines_to_y (0),
chars_to_x (30) + PAGER_WIDTH,
lines_to_y (1),
1, background, background);
XSelectInput (page_window, ExposeWindow);
/* The real shape of the page_subwindow will be determined when */
/* show_slider is called. */
page_subwindow = XCreateWindow (page_window, 1, 1, 1, 1,
1,
foreground, background);
XSelectInput (page_subwindow, LeaveWindow | MouseMoved |
ButtonPressed | ButtonReleased);
callouttable = XCreateAssocTable (2);
offsets = XCreateAssocTable (2);
create_buttons ();
XMapSubwindows (panel);
/* + 1 and -1 below are to account for the border around the pane. */
textwindow =
XCreateWindow (frame, 0, panelheight + 1,
screenwidth, textwindowheight,
0, foreground, background);
XSelectInput (textwindow, ExposeWindow);
}
XMapSubwindows (frame);
XMapWindow (frame);
reset_scroll ();
if (current_file_name [0]) {
load_proc ();
};
for (;;) {
char *string;
XEvent e;
void (*callout) ();
XNextEvent (&e);
callout = (void (*)()) XLookUpAssoc (callouttable, e.window);
switch (e.type) {
case KeyPressed:
{
int length;
char *string;
string = XLookupMapping (&e, &length);
if (length) {
for (;length; string++,length--) {
if (*string == '\010' || *string == '\177') {
if (*current_file_name) {
current_file_name_index--;
current_file_name [current_file_name_index - 1] = '\0';
}
} else {
current_file_name [current_file_name_index - 1] = *string;
vector_push_extend (¤t_file_name_index,
¤t_file_name_length,
¤t_file_name,
sizeof (char));
current_file_name [current_file_name_index - 1] = '\0';
}
}
}
update_filename ();
}
break;
case MouseMoved:
/* The event must be in page_subwindow. */
curpage_from_x (&e);
break;
case LeaveWindow:
/* The event must be in page_subwindow. */
page_displayed = page_current;
refresh_slider ();
break;
case ButtonPressed:
if (e.window == page_subwindow) {
curpage_from_x (&e);
page_current = page_displayed;
goto_page (page_current);
} else if (!callout) {
buttondown (((XKeyEvent *) &e) -> x,
((XKeyEvent *) &e) -> y);
};
break;
case ButtonReleased:
if (e.window == page_subwindow) {
/* Do nothing. */
} else if (callout) {
(*callout) ();
} else {
buttonup (((XKeyEvent *) &e) -> x,
((XKeyEvent *) &e) -> y);
};
break;
case ExposeWindow:
if (e.window == filename_button) {
update_filename ();
} else if (e.window == error_button) {
update_error ();
} else if (e.window == page_window ) {
refresh_slider ();
} else if (callout) {
char *name;
int offset;
offset = (int) XLookUpAssoc (offsets, e.window);
XFetchName (e.window, &name);
dotext (e.window,
BUTTONMARGIN + offset, BUTTONMARGIN,
name);
free (name);
} else if ((e.window == frame) &&
(((XExposeEvent *) &e) -> subwindow == 0)) {
if ((screenwidth != ((XExposeEvent *) &e) -> width) ||
(screenheight != ((XExposeEvent *) &e) -> height)) {
screenwidth = ((XExposeEvent *) &e) -> width;
screenheight = ((XExposeEvent *) &e) -> height;
textwindowheight = screenheight - panelheight;
XChangeWindow (panel, screenwidth, panelheight);
XChangeWindow (textwindow, screenwidth,
textwindowheight);
}
} else if (e.window == textwindow) {
refresh_proc ();
};
break;
};
};
};